package fun.qu_an.minecraft.fabric.fzbbl.mixin;

import fun.qu_an.minecraft.fabric.fzbbl.event.PistonEvents;
import net.minecraft.block.BlockState;
import net.minecraft.block.PistonBlock;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(PistonBlock.class)
public abstract class PistonBlockMixin {
	@Inject(method = "onSyncedBlockEvent", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z"), cancellable = true)
	public void onPistonExtending(BlockState state, World world, BlockPos pos, int type, int data, CallbackInfoReturnable<Boolean> cir) {
		if (!PistonEvents.EXTENDING.invoker().extending(world, pos, state)) {
			cir.setReturnValue(false);
		}
	}

	@Inject(method = "onSyncedBlockEvent", at = @At(
		value = "INVOKE",
		ordinal = 0,
		target = "Lnet/minecraft/world/World;emitGameEvent(Lnet/minecraft/entity/Entity;Lnet/minecraft/world/event/GameEvent;Lnet/minecraft/util/math/BlockPos;)V",
		shift = At.Shift.AFTER
	))
	public void onPistonExtended(BlockState state, World world, BlockPos pos, int type, int data, CallbackInfoReturnable<Boolean> cir) {
		PistonEvents.EXTENDED.invoker().extended(world, pos, state);
	}

	@Inject(method = "onSyncedBlockEvent", at = @At(
		value = "INVOKE",
		ordinal = 0,
		target = "Lnet/minecraft/world/World;getBlockEntity(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/entity/BlockEntity;"
	), cancellable = true)
	public void onPistonContracting(BlockState state, World world, BlockPos pos, int type, int data, CallbackInfoReturnable<Boolean> cir) {
		if (!PistonEvents.CONTRACTING.invoker().contracting(world, pos, state)) {
			cir.setReturnValue(false);
		}
	}

	@Inject(method = "onSyncedBlockEvent", at = @At(
		value = "INVOKE",
		shift = At.Shift.AFTER,
		ordinal = 1,
		target = "Lnet/minecraft/world/World;emitGameEvent(Lnet/minecraft/entity/Entity;Lnet/minecraft/world/event/GameEvent;Lnet/minecraft/util/math/BlockPos;)V"
	))
	public void onPistonContracted(BlockState state, World world, BlockPos pos, int type, int data, CallbackInfoReturnable<Boolean> cir) {
		PistonEvents.CONTRACTED.invoker().contracted(world, pos, state);
	}
}
